#include "etcd.hpp"
#include "channel.hpp"
#include "main.pb.h"
#include <butil/logging.h>
#include <gflags/gflags.h>
#include <thread>

DEFINE_bool(run_mode, false, "程序的运行模式,格式:true:发布模式/false:调试模式");
DEFINE_string(log_filename, "", "发布模式下使用的文件名");
DEFINE_int32(log_level, 0, "发布模式下设置的日志输出等级");
DEFINE_string(base_service, "/service", "服务监控根目录");
DEFINE_string(etcd_host, "http://127.0.0.1:2379", "服务注册中心地址");
DEFINE_string(call_service, "/service/echo", "调用哪些服务");

int main(int argc, char *argv[])
{
    google::ParseCommandLineFlags(&argc, &argv, true);
    init_logger(FLAGS_run_mode, FLAGS_log_filename, FLAGS_log_level);
    // 发现端改造思想：
    auto sm = std::make_shared<ServiceManager>();
    // 1、构造Rpc信道管理，设置关心服务
    sm->declared(FLAGS_call_service);
    auto put_cb = std::bind(&ServiceManager::OnServiceOnline, sm.get(), std::placeholders::_1, std::placeholders::_2);
    auto del_cb = std::bind(&ServiceManager::OnServiceOffline, sm.get(), std::placeholders::_1, std::placeholders::_2);
    // 2、构造服务发现对象
    std::shared_ptr<Discoverer> client_ptr = std::make_shared<Discoverer>(FLAGS_etcd_host, FLAGS_base_service, put_cb, del_cb);
    // 3、通过Rpc信道管理对象，获取提供Echo服务的信道

    // 4、发起EchoRpc调用
    while (true)
    {
        auto channel = sm->choose(FLAGS_call_service);
        if (channel.get() == nullptr)
        {
            std::this_thread::sleep_for(std::chrono::seconds(1));
            continue;
        }
        example::EchoService_Stub stub(channel.get());
        example::EchoRequest req;
        req.set_message("this is a message! ");
        brpc::Controller *cntl = new brpc::Controller();
        example::EchoResponse *resp = new example::EchoResponse();
        stub.Echo(cntl, &req, resp, nullptr);
        if (cntl->Failed() == true)
        {
            std::cout << "Rpc调用失败: " << cntl->ErrorText() << std::endl;
            std::this_thread::sleep_for(std::chrono::seconds(1));
            delete cntl;
            delete resp;
            continue;
        }
        std::cout << "收到响应: " << resp->message() << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
    return 0;
}